package com.zhiche.lisa.core.utils;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    //编码格式。发送编码格式统一用UTF-8
    private static String ENCODING = "UTF-8";

    /**
     * 基于HttpClient 4.3的通用POST方法
     *
     * @param url       提交的URL
     * @param paramsMap 提交<参数，值>Map
     * @return 提交响应
     */
    public static String post(String url, List<NameValuePair> headerParams, Map<String, String> paramsMap, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {

            HttpPost method = new HttpPost(url);
            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            if (paramsMap != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (Map.Entry<String, String> param : paramsMap.entrySet()) {
                    NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
                    paramList.add(pair);
                }
                method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING));
            }
            //添加header
            if (!CollectionUtils.isEmpty(headerParams)) {
                for (NameValuePair param : headerParams) {
                    method.setHeader(param.getName(), param.getValue());
                }
            }
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseText = EntityUtils.toString(entity, ENCODING);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.post url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }

    /**
     * 发起JSON的POST请求
     *
     * @param url
     * @param headerParams
     * @param params
     * @param socketTimeout
     * @return
     */
    public static String postJson(String url, List<NameValuePair> headerParams, String params, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {

            HttpPost method = new HttpPost(url);
            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            //添加header
            if (!CollectionUtils.isEmpty(headerParams)) {
                for (NameValuePair param : headerParams) {
                    method.setHeader(param.getName(), param.getValue());
                }
            }
            if (!StringUtils.isEmpty(params)) {
                StringEntity entity = new StringEntity(params, ENCODING);//解决中文乱码问题
                entity.setContentEncoding(ENCODING);
                entity.setContentType("application/json");
                method.setEntity(entity);
            }
            response = client.execute(method);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity he = response.getEntity();
                if (he != null) {
                    responseText = EntityUtils.toString(he, ENCODING);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.postJson url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }

    /**
     * 发起JSON的POST请求
     *
     * @param url
     * @param headerParams
     * @param params
     * @param socketTimeout
     * @return
     */
    public static String postJsoneRturnError(String url, List<NameValuePair> headerParams, String params, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {
            HttpPost method = new HttpPost(url);
            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            //添加header
            if (!CollectionUtils.isEmpty(headerParams)) {
                for (NameValuePair param : headerParams) {
                    method.setHeader(param.getName(), param.getValue());
                }
            }
            if (!StringUtils.isEmpty(params)) {
                StringEntity entity = new StringEntity(params, ENCODING);//解决中文乱码问题
                entity.setContentEncoding(ENCODING);
                entity.setContentType("application/json");
                method.setEntity(entity);
            }
            response = client.execute(method);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity he = response.getEntity();
                if (he != null) {
                    responseText = EntityUtils.toString(he, ENCODING);
                }
            }
            if (response.getStatusLine().getStatusCode() == 500) {
                HttpEntity he = response.getEntity();
                if (he != null) {
                    responseText = EntityUtils.toString(he, ENCODING);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.postJsoneRturnError url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }

    /**
     * 基于HttpClient 4.3的通用POST方法
     *
     * @param url       提交的URL
     * @param paramsMap 提交<参数，值>Map
     * @return 提交响应
     */
    public static String post(String url, Map<String, String> paramsMap, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {

            HttpPost method = new HttpPost(url);
            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            if (paramsMap != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (Map.Entry<String, String> param : paramsMap.entrySet()) {
                    NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
                    paramList.add(pair);
                }
                method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING));
            }
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseText = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.post url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }


    /**
     * 发起POST请求
     *
     * @param url
     * @param param
     * @return
     */
    public static String post(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
            logger.info("http.post url: {}, 异常信息 {}", url, e.getMessage());
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发起POST请求
     *
     * @param url
     * @param param
     * @return
     */
    public static String postUTF(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Content-Type", "pplication/json;charset=UTF-8");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
            logger.info("http.postUTF url: {}, 异常信息 {}", url, e.getMessage());
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 基于HttpClient 4.3的通用Get方法
     *
     * @param url
     * @param params 参数
     * @return
     */
    public static String get(String url, List<NameValuePair> headerParams, List<NameValuePair> params, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        HttpGet method = null;

        try {
            if (!CollectionUtils.isEmpty(params)) {
                String str = EntityUtils.toString(new UrlEncodedFormEntity(params, ENCODING));
                method = new HttpGet(url + "?" + str);
            } else {
                method = new HttpGet(url);
            }

            //添加header
            if (!CollectionUtils.isEmpty(headerParams)) {
                for (NameValuePair param : headerParams) {
                    method.setHeader(param.getName(), param.getValue());
                }
            }

            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (!Objects.isNull(entity)) {
                responseText = EntityUtils.toString(entity, ENCODING);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.get url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }

    /**
     * 基于HttpClient 4.3的通用Get方法
     *
     * @param url
     * @param params 参数
     * @return
     */
    public static String get(String url, List<NameValuePair> params, int socketTimeout) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        HttpGet method = null;

        try {
            if (!CollectionUtils.isEmpty(params)) {
                String str = EntityUtils.toString(new UrlEncodedFormEntity(params, ENCODING));
                method = new HttpGet(url + "?" + str);
            } else {
                method = new HttpGet(url);
            }
            RequestConfig.Builder builder = RequestConfig.custom().setConnectTimeout(300000).setSocketTimeout(socketTimeout);
            method.setConfig(builder.build());
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseText = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("http.get url: {}, 异常信息 {}", url, e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(response)) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return responseText;
    }


    /**
     * get
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }


    /**
     * post form
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      Map<String, String> bodys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();

            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }

    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Post stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Put String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Put stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Delete
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doDelete(String host, String path, String method,
                                        Map<String, String> headers,
                                        Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }

    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    private static HttpClient wrapClient(String host) {
        HttpClient httpClient = new DefaultHttpClient();
//		if (host.startsWith("https://")) {
//			sslClient(httpClient);
//		}

        return httpClient;
    }

//	private static void sslClient(HttpClient httpClient) throws NoSuchAlgorithmException, KeyManagementException {
//		try {
//			SSLContext ctx = SSLContext.getInstance("TLS");
//			X509TrustManager tm = new X509TrustManager() {
//				public X509Certificate[] getAcceptedIssuers() {
//					return null;
//				}
//				public void checkClientTrusted(X509Certificate[] xcs, String str) {
//
//				}
//				public void checkServerTrusted(X509Certificate[] xcs, String str) {
//
//				}
//			};
//			ctx.init(null, new TrustManager[] { tm }, null);
//			SSLSocketFactory ssf = new SSLSocketFactory(ctx);
//			ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//			ClientConnectionManager ccm = httpClient.getConnectionManager();
//			SchemeRegistry registry = ccm.getSchemeRegistry();
//			registry.register(new Scheme("https", 443, ssf));
//		} catch (KeyManagementException ex) {
//			throw new RuntimeException(ex);
//		} catch (NoSuchAlgorithmException ex) {
//			throw new RuntimeException(ex);
//		}
//	}

    /**
     * 发起xml的POST请求
     *
     * @param url
     * @param xml
     * @return
     * @throws Exception
     */
    public static String postXml(String url, String xml)
            throws Exception {
        String result = "";
        CloseableHttpClient httpClient = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);//Post请求
            // 设置实体 优先级高
            if (StringUtils.isNotBlank(xml)) {
                StringEntity entity = new StringEntity(xml, "UTF-8");
                httpPost.addHeader("Content-Type", "text/xml");
                httpPost.setEntity(entity);
            }
            HttpResponse httpResponse = httpClient.execute(httpPost);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity resEntity = httpResponse.getEntity();
                result = EntityUtils.toString(resEntity);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpClient != null) {
                httpClient.close();
            }
        }
        return result;
    }

}
